Įsisavinkite TypeScript deklaracijų failus (.d.ts), kad užtikrintumėte tipų saugumą ir automatinį užbaigimą bet kuriai JavaScript bibliotekai. Išmokite naudoti @types, kurti savo apibrėžimus ir profesionaliai dirbti su trečiųjų šalių kodu.
JavaScript Ekosistemos Atrakinimas: Gilus Pasinėrimas į TypeScript Deklaracijų Failus
TypeScript sukėlė revoliuciją šiuolaikiniame žiniatinklio programavime, įnešdamas statinį tipizavimą į dinamišką JavaScript pasaulį. Šis tipų saugumas suteikia neįtikėtinų privalumų: klaidų fiksavimas kompiliavimo metu, galingas redaktoriaus automatinis kodo užbaigimas ir žymiai lengviau prižiūrimos didelės kodo bazės. Tačiau iškyla didelis iššūkis, kai norime naudoti didžiulę esamų JavaScript bibliotekų ekosistemą – dauguma jų nebuvo parašytos TypeScript kalba. Kaip mūsų griežtai tipizuotas TypeScript kodas supranta formas, funkcijas ir kintamuosius iš netipizuotos JavaScript bibliotekos?
Atsakymas slypi TypeScript Deklaracijų Failuose. Šie failai, atpažįstami pagal .d.ts plėtinį, yra esminis tiltas tarp TypeScript ir JavaScript pasaulių. Jie veikia kaip šablonas arba API kontraktas, aprašantis trečiosios šalies bibliotekos tipus, tačiau neturintis jokios faktinės jos implementacijos. Šiame išsamiame vadove išnagrinėsime viską, ką reikia žinoti, kad užtikrintai valdytumėte bet kurios JavaScript bibliotekos tipų apibrėžimus savo TypeScript projektuose.
Kas Tiksliai Yra TypeScript Deklaracijų Failai?
Įsivaizduokite, kad pasamdėte rangovą, kuris kalba tik kita kalba. Norėdami su juo efektyviai dirbti, jums prireiktų vertėjo arba išsamių instrukcijų kalba, kurią abu suprantate. Deklaracijos failas atlieka būtent šią funkciją TypeScript kompiliatoriui (rangovui).
.d.ts faile yra tik tipų informacija. Ji apima:
- Funkcijų ir metodų signatūras (parametrų tipai, grąžinimo tipai).
- Kintamųjų ir jų tipų apibrėžimus.
- Sąsajas (interfaces) ir tipų aliasus sudėtingiems objektams.
- Klasių apibrėžimus, įskaitant jų savybes ir metodus.
- Vardų erdvių (namespace) ir modulių struktūras.
Svarbiausia, šiuose failuose nėra jokio vykdomojo kodo. Jie skirti tik statinei analizei. Kai importuojate JavaScript biblioteką, pavyzdžiui, Lodash, į savo TypeScript projektą, kompiliatorius ieško atitinkamo deklaracijos failo. Jei jį randa, jis gali patvirtinti jūsų kodą, pateikti išmanųjį automatinį užbaigimą ir užtikrinti, kad biblioteką naudojate teisingai. Jei neranda, jis išmes klaidą, pavyzdžiui: Could not find a declaration file for module 'lodash'.
Kodėl Deklaracijų Failai Yra Būtini Profesionaliam Programavimui
Naudojant JavaScript bibliotekas be tinkamų tipų apibrėžimų TypeScript projekte, kenkiama pačiai TypeScript naudojimo esmei. Panagrinėkime paprastą scenarijų naudojant populiarią pagalbinių funkcijų biblioteką „Lodash“.
Pasaulis Be Tipų Apibrėžimų
Be deklaracijos failo, TypeScript neįsivaizduoja, kas yra lodash ir ką jis apima. Kad kodas bent jau kompiliuotųsi, gali kilti pagunda pasinaudoti greitu sprendimu, pavyzdžiui, šiuo:
const _: any = require('lodash');
const users = [{ 'user': 'barney' }, { 'user': 'fred' }];
// Automatinis užbaigimas? Jokios pagalbos.
// Tipų tikrinimas? Ne. Ar 'username' yra teisinga savybė?
// Kompiliatorius tai leidžia, bet programa gali sugesti vykdymo metu.
_.find(users, { username: 'fred' });
Šiuo atveju, _ kintamasis yra any tipo. Tai iš esmės nurodo TypeScript: „Netikrink nieko, kas susiję su šiuo kintamuoju“. Jūs prarandate visus privalumus: jokio automatinio užbaigimo, jokio argumentų tipų tikrinimo ir jokio tikrumo dėl grąžinamo tipo. Tai yra terpė vykdymo meto klaidoms.
Pasaulis Su Tipų Apibrėžimais
Dabar pažiūrėkime, kas nutinka, kai pateikiame būtiną deklaracijos failą. Įdiegus tipus (ką aptarsime toliau), patirtis visiškai pasikeičia:
import _ from 'lodash';
interface User {
user: string;
active?: boolean;
}
const users: User[] = [{ 'user': 'barney' }, { 'user': 'fred' }];
// 1. Redaktorius pateikia automatinį užbaigimą 'find' ir kitoms lodash funkcijoms.
// 2. Užvedus pelę ant 'find' rodomas pilnas signatūros aprašymas ir dokumentacija.
// 3. TypeScript mato, kad `users` yra `User` objektų masyvas.
// 4. TypeScript žino, kad `find` predikatas `User[]` masyvui turėtų naudoti `user` arba `active`.
// TEISINGAI: TypeScript patenkintas.
const fred = _.find(users, { user: 'fred' });
// KLAIDA: TypeScript pagauna klaidą!
// Savybė 'username' neegzistuoja 'User' tipe.
const betty = _.find(users, { username: 'betty' });
Skirtumas yra kaip diena ir naktis. Mes gauname visišką tipų saugumą, geresnę programuotojo patirtį dėl įrankių ir dramatiškai sumažiname galimų klaidų skaičių. Tai yra profesionalus standartas dirbant su TypeScript.
Tipų Apibrėžimų Radimo Hierarchija
Taigi, kaip gauti šiuos magiškus .d.ts failus savo mėgstamoms bibliotekoms? Yra nusistovėjęs procesas, apimantis didžiąją daugumą scenarijų.
1 Žingsnis: Patikrinkite, ar Biblioteka Turi Savo Tipus
Geriausias scenarijus yra, kai biblioteka parašyta TypeScript kalba arba jos prižiūrėtojai pateikia oficialius deklaracijų failus tame pačiame pakete. Tai tampa vis dažnesniu reiškiniu šiuolaikiniuose, gerai prižiūrimuose projektuose.
Kaip patikrinti:
- Įdiekite biblioteką kaip įprasta:
npm install axios - Pažiūrėkite į bibliotekos aplanką
node_modules/axios. Ar matote kokius nors.d.tsfailus? - Patikrinkite bibliotekos
package.jsonfailą ieškodami"types"arba"typings"lauko. Šis laukas tiesiogiai nurodo į pagrindinį deklaracijos failą. Pavyzdžiui, Axiospackage.jsonfaile yra:"types": "index.d.ts".
Jei šios sąlygos įvykdytos, viskas! TypeScript automatiškai suras ir naudos šiuos integruotus tipus. Jokių papildomų veiksmų nereikia.
2 Žingsnis: DefinitelyTyped Projektas (@types)
Tūkstančiams JavaScript bibliotekų, kurios neturi savo tipų, pasaulinė TypeScript bendruomenė sukūrė neįtikėtiną resursą: DefinitelyTyped.
DefinitelyTyped yra centralizuota, bendruomenės valdoma repozitorija GitHub'e, kurioje talpinami aukštos kokybės deklaracijų failai didžiuliam skaičiui JavaScript paketų. Šie apibrėžimai yra publikuojami npm registre po @types sritimi.
Kaip jį naudoti:
Jei biblioteka, pavyzdžiui, lodash, neturi savo tipų, jūs tiesiog įdiegiate atitinkamą @types paketą kaip programavimo priklausomybę:
npm install --save-dev @types/lodash
Pavadinimų suteikimo tvarka yra paprasta ir nuspėjama: paketui, pavadintam package-name, jo tipai beveik visada bus @types/package-name. Galimų tipų galite ieškoti npm svetainėje arba tiesiogiai DefinitelyTyped repozitorijoje.
Kodėl --save-dev? Deklaracijų failai reikalingi tik programavimo ir kompiliavimo metu. Juose nėra jokio vykdymo kodo, todėl jie neturėtų būti įtraukti į jūsų galutinį produkcinį paketą. Įdiegus juos kaip devDependency, užtikrinamas šis atskyrimas.
3 Žingsnis: Kai Tipų Nėra – Rašykite Savus
Ką daryti, jei naudojate senesnę, nišinę ar vidinę privačią biblioteką, kuri neturi integruotų tipų ir nėra DefinitelyTyped projekte? Tokiu atveju turite atsiraitoti rankoves ir sukurti savo deklaracijos failą. Nors tai gali skambėti bauginančiai, galite pradėti nuo paprasto varianto ir prireikus pridėti daugiau detalių.
Greitas Sprendimas: Sutrumpinta Aplinkos Modulio Deklaracija
Kartais jums tiesiog reikia, kad projektas kompiliuotųsi be klaidų, kol išsiaiškinsite tinkamą tipizavimo strategiją. Galite sukurti failą savo projekte (pvz., declarations.d.ts arba types/global.d.ts) ir pridėti sutrumpintą deklaraciją:
// .d.ts faile
declare module 'some-untyped-library';
Tai nurodo TypeScript: „Patikėk manimi, modulis pavadinimu 'some-untyped-library' egzistuoja. Tiesiog viską, kas iš jo importuojama, laikyk any tipo.“ Tai nutildo kompiliatoriaus klaidą, tačiau, kaip jau aptarėme, paaukoja visą tos bibliotekos tipų saugumą. Tai laikinas pataisymas, o ne ilgalaikis sprendimas.
Pagrindinio Individualaus Deklaracijos Failo Kūrimas
Geresnis požiūris – pradėti apibrėžti tipus toms bibliotekos dalims, kurias iš tikrųjų naudojate. Tarkime, turime paprastą biblioteką, pavadintą `string-utils`, kuri eksportuoja vieną funkciją.
// node_modules/string-utils/index.js faile
module.exports.capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);
Galime sukurti string-utils.d.ts failą specialiame `types` kataloge mūsų projekto šakninėje direktorijoje.
// my-project/types/string-utils.d.ts faile
declare module 'string-utils' {
export function capitalize(str: string): string;
// Čia galite pridėti kitų funkcijų apibrėžimus, kai juos naudojate
// export function slugify(str: string): string;
}
Dabar turime nurodyti TypeScript, kur rasti mūsų individualius tipų apibrėžimus. Tai darome tsconfig.json faile:
{
"compilerOptions": {
// ... kitos parinktys
"baseUrl": ".",
"paths": {
"*": ["types/*"]
}
}
}
Su šia konfigūracija, kai vykdysite import { capitalize } from 'string-utils', TypeScript ras jūsų individualų deklaracijos failą ir suteiks jūsų apibrėžtą tipų saugumą. Galite palaipsniui plėsti šį failą, kai naudojate daugiau bibliotekos funkcijų.
Giliau: Deklaracijų Failų Kūrimas
Panagrinėkime keletą pažangesnių koncepcijų, su kuriomis susidursite rašydami ar skaitydami deklaracijų failus.
Skirtingų Eksporto Tipų Deklaravimas
JavaScript moduliai gali eksportuoti įvairiais būdais. Jūsų deklaracijos failas turi atitikti bibliotekos eksporto struktūrą.
- Vardiniai Eksportai (Named Exports): Tai labiausiai paplitęs būdas. Jį matėme aukščiau su `export function capitalize(...)`. Taip pat galite eksportuoti konstantas, sąsajas ir klases.
- Numatytasis Eksportas (Default Export): Bibliotekoms, kurios naudoja `export default`.
- UMD Globalūs Kintamieji: Senesnėms bibliotekoms, sukurtoms veikti naršyklėse per
<script>žymę, jos dažnai prisikabina prie globalaus `window` objekto. Galite deklaruoti šiuos globalius kintamuosius. - `export =` ir `import = require()`: Ši sintaksė skirta senesniems CommonJS moduliams, kurie naudoja `module.exports = ...`. Pavyzdžiui, jei biblioteka daro `module.exports = myClass;`.
declare module 'my-lib' {
export const version: string;
export interface Options { retries: number; }
export function doSomething(options: Options): Promise
declare module 'my-default-lib' {
// Funkcijos numatytajam eksportui
export default function myCoolFunction(): void;
// Objekto numatytajam eksportui
// const myLib = { name: 'lib', version: '1.0' };
// export default myLib;
}
// Deklaruoja globalų kintamąjį '$' tam tikro tipo
declare var $: JQueryStatic;
// my-class.d.ts faile
declare class MyClass { constructor(name: string); }
export = MyClass;
// jūsų app.ts faile
import MyClass = require('my-class');
const instance = new MyClass('test');
Nors tai rečiau pasitaiko su moderniais ES moduliais, tai yra kritiškai svarbu suderinamumui su daugeliu senesnių, bet vis dar plačiai naudojamų Node.js paketų.
Modulių Papildymas: Esamų Tipų Išplėtimas
Viena iš galingiausių funkcijų yra modulių papildymas (dar žinomas kaip deklaracijų suliejimas). Tai leidžia pridėti savybių prie esamų sąsajų, apibrėžtų kito paketo deklaracijos faile. Tai ypač naudinga bibliotekoms su įskiepių architektūra, pavyzdžiui, Express ar Fastify.
Įsivaizduokite, kad naudojate tarpinę programinę įrangą (middleware) Express'e, kuri prideda `user` savybę prie `Request` objekto. Be papildymo, TypeScript skųstųsi, kad `user` neegzistuoja `Request` tipe.
Štai kaip galite pranešti TypeScript apie šią naują savybę:
// jūsų types/express.d.ts faile
// Turime importuoti originalų tipą, kad jį papildytume
import { UserProfile } from './auth'; // Darant prielaidą, kad turite UserProfile tipą
// Nurodome TypeScript, kad papildome 'express-serve-static-core' modulį
declare module 'express-serve-static-core' {
// Nurodome 'Request' sąsają tame modulyje
interface Request {
// Pridedame savo individualią savybę
user?: UserProfile;
}
}
Dabar visoje jūsų programoje Express `Request` objektas bus teisingai tipizuotas su pasirenkama `user` savybe, ir jūs gausite pilną tipų saugumą bei automatinį užbaigimą.
Trigubo Pasvirojo Brūkšnio Direktyvos
Kartais .d.ts failų viršuje galite pamatyti komentarus, prasidedančius trimis pasviraisiais brūkšniais (///). Tai yra trigubo pasvirojo brūkšnio direktyvos, kurios veikia kaip kompiliatoriaus instrukcijos.
/// <reference types="..." />: Tai labiausiai paplitusi direktyva. Ji aiškiai įtraukia kito paketo tipų apibrėžimus kaip priklausomybę. Pavyzdžiui, WebdriverIO įskiepio tipai gali turėti/// <reference types="webdriverio" />, nes jo paties tipai priklauso nuo pagrindinių WebdriverIO tipų./// <reference path="..." />: Tai naudojama deklaruoti priklausomybę nuo kito failo tame pačiame projekte. Tai senesnė sintaksė, kurią daugiausia pakeitė ES modulių importai.
Geriausios Praktikos Tvarkant Deklaracijų Failus
- Teikite pirmenybę integruotiems tipams: Renkantis bibliotekas, pirmenybę teikite toms, kurios parašytos TypeScript kalba arba pateikia savo oficialius tipų apibrėžimus. Tai rodo įsipareigojimą TypeScript ekosistemai.
- Laikykite
@typesdevDependencies: Visada diekite@typespaketus su--save-devarba-D. Jie nėra reikalingi jūsų produkciniam kodui. - Suderinkite versijas: Dažna klaidų priežastis yra nesutapimas tarp bibliotekos versijos ir jos
@typesversijos. Didelis bibliotekos versijos šuolis (pvz., nuo v2 iki v3) greičiausiai turės esminių pakeitimų savo API, kurie turi atsispindėti@typespakete. Stenkitės juos sinchronizuoti. - Naudokite
tsconfig.jsonvaldymui:typeRootsirtypeskompiliatoriaus parinktys jūsųtsconfig.jsonfaile gali suteikti jums smulkmenišką kontrolę, kur TypeScript ieško deklaracijų failų.typeRootsnurodo kompiliatoriui, kuriuos aplankus tikrinti (pagal nutylėjimą tai yra./node_modules/@types), otypesleidžia aiškiai nurodyti, kuriuos tipų paketus įtraukti. - Prisidėkite prie bendruomenės: Jei parašote išsamų deklaracijos failą bibliotekai, kuri jo neturi, apsvarstykite galimybę prisidėti prie DefinitelyTyped projekto. Tai puikus būdas atsilyginti pasaulinei programuotojų bendruomenei ir padėti tūkstančiams kitų.
Išvada: Neapdainuoti Tipų Saugumo Herojai
TypeScript Deklaracijų Failai yra neapdainuoti herojai, kurie leidžia sklandžiai integruoti dinamišką, platų JavaScript pasaulį į tvirtą, tipams saugią programavimo aplinką. Jie yra kritinė grandis, kuri suteikia galios mūsų įrankiams, apsaugo nuo nesuskaičiuojamų klaidų ir daro mūsų kodo bazes atsparesnes ir savaime dokumentuojančias.
Suprasdami, kaip rasti, naudoti ir net kurti savo .d.ts failus, jūs ne tik ištaisote kompiliatoriaus klaidą – jūs pakeliate visą savo programavimo procesą į aukštesnį lygį. Jūs atveriate visą TypeScript ir turtingos JavaScript bibliotekų ekosistemos potencialą, sukurdami galingą sinergiją, kurios rezultatas – geresnė ir patikimesnė programinė įranga pasaulinei auditorijai.